package com.chance.cc.crawler.development.scripts.weibo.subscribe;

import com.alibaba.fastjson.JSONObject;
import com.chance.cc.crawler.core.CrawlerRecordContext;
import com.chance.cc.crawler.core.downloader.HttpConstant;
import com.chance.cc.crawler.core.downloader.HttpPage;
import com.chance.cc.crawler.core.downloader.HttpRequest;
import com.chance.cc.crawler.core.downloader.HttpRequestBody;
import com.chance.cc.crawler.core.pipeline.result.CrawlerData;
import com.chance.cc.crawler.core.record.CrawlerRecord;
import com.chance.cc.crawler.core.record.CrawlerRequestRecord;
import com.chance.cc.crawler.core.script.crawler.CrawlerCommonScript;
import com.chance.cc.crawler.core.tags.crawler.CrawlerBusinessTags;
import com.chance.cc.crawler.core.tags.crawler.CrawlerResultTags;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.chance.cc.crawler.core.CrawlerEnum.CrawlerDataType.article;

/**
 * @Author Zhao.Hhuan
 * @Date Create in 2021/4/12 15:54
 * @Description
 *      修改订阅的用户或关键词
 **/
public class WeiboApiUpdateSubscribeUserIdOrKeywordCrawlerScript extends CrawlerCommonScript {

    private static Logger log = LoggerFactory.getLogger(WeiboApiUpdateSubscribeUserIdOrKeywordCrawlerScript.class);

    private static final String DOMAIN = "weibo";
    private static final String SITE = "updateSubscribe";
    private static final String REQUEST_AGAIN_TAG = DOMAIN + "_api_request_retry";
    private static final String SOURCE = "source";
    private static final String SUBID = "subid";

    private static final String UPDATE_SUBSCRIBE = "https://c.api.weibo.com/subscribe/update_subscribe.json";

    /**
     * 脚本domain定义
     *
     * @return
     */
    @Override
    public String domain() {
        return DOMAIN;
    }

    /**
     * 进入脚本的正则列表
     */
    @Override
    public void initUrlRegulars() {
        addUrlRegular(UPDATE_SUBSCRIBE);
    }

    @Override
    public List<CrawlerRecord> prepareRequest(CrawlerRequestRecord requestRecord, List<CrawlerRequestRecord> supportSourceRecords) {
        List<CrawlerRecord> crawlerRecords = new ArrayList<>();
        for (CrawlerRequestRecord supportSourceRecord : supportSourceRecords) {
            String supportRequestUrl = supportSourceRecord.getHttpRequest().getUrl();
            if (supportRequestUrl.contains("keys")) {
                initKeywordRecord(requestRecord, supportSourceRecord, crawlerRecords);
            }
        }
        return crawlerRecords;
    }
    /**
     * 是否执行脚本 ： 输入数据检查，合格的才进入脚本
     *
     * @param crawlerRequestRecord
     * @return
     */
    @Override
    public boolean crawlerCheck(CrawlerRequestRecord crawlerRequestRecord) {
        String site = crawlerRequestRecord.tagsCreator().bizTags().getCategoryTag().getKVTagStrVal("site");
        return site.startsWith(SITE);
    }

    /**
     * 解析链接方法
     *
     * @param crawlerRequestRecord
     * @param httpPage
     * @return
     */
    @Override
    public List<CrawlerRequestRecord> parseLinks(CrawlerRequestRecord crawlerRequestRecord, HttpPage httpPage) {
        List<CrawlerRequestRecord> parsedLinks = new ArrayList<>();
        if (!httpPage.isDownloadSuccess() || httpPage.getStatusCode() == 503) {
            log.error("weibo api url down load page is fail!will retry");
            requestAgainCrawlerRecord(parsedLinks, crawlerRequestRecord);
            crawlerRequestRecord.setNeedWashPage(false);
            return parsedLinks;
        }
        return parsedLinks;
    }

    @Override
    public List<CrawlerData> washPage(CrawlerRequestRecord crawlerRecord, HttpPage page) {
        List<CrawlerData> crawlerDataList = new ArrayList<>();
        CrawlerResultTags crawlerResultTags = crawlerRecord.tagsCreator().resultTags();

        if (crawlerResultTags.hasDataType(article)) {
            crawlerDataList.add(washArticle(crawlerRecord,page));
        }

        return crawlerDataList;
    }

    private CrawlerData washArticle(CrawlerRequestRecord requestRecord, HttpPage httpPage) {
        String itemUrl = httpPage.getRequest().getUrl();
        String keyword = (String) httpPage.getRequest().getExtras().get("keyword");

        CrawlerData crawlerData = CrawlerData.builder()
                    .data(requestRecord, httpPage)
                    .dataId(keyword)
                    .url(itemUrl)
                    .content(httpPage.getRawText())
                    .build();

        return crawlerData;
    }

    private void requestAgainCrawlerRecord(List<CrawlerRequestRecord> crawlerRequestRecords, CrawlerRequestRecord crawlerRecord) {

        CrawlerBusinessTags crawlerBusinessTags = crawlerRecord.tagsCreator().bizTags();
        int count = 0;
        if (crawlerBusinessTags.hasKVTag(REQUEST_AGAIN_TAG)) {
            count = (int) crawlerBusinessTags.getCategoryTag().getKVTag(REQUEST_AGAIN_TAG).getVal();
            if (count >= 5) {
                log.error("Weibo search keyword download page the number of retries exceeds the limit" +
                        ",request url {},download detail {}", crawlerRecord.getHttpRequest().getUrl());
                return;
            }
        }

        CrawlerRequestRecord crawlerRequestRecord = CrawlerRequestRecord.builder()
                .itemPageRequest(crawlerRecord)
                .httpUrl(crawlerRecord.getHttpRequest().getUrl())
                .recordKey(crawlerRecord.getRecordKey() + count)
                .releaseTime(System.currentTimeMillis())
                .copyBizTags()
                .copyResultTags()
                .build();

        String method = crawlerRecord.getHttpRequest().getMethod();
        if(HttpConstant.Method.POST.equals(method)){
            HttpRequest httpRequest = crawlerRequestRecord.getHttpRequest();
            httpRequest.setMethod(method);
            httpRequest.setRequestBody(crawlerRecord.getHttpRequest().getRequestBody());
        }

        crawlerRequestRecord.getHttpRequest().setExtras(crawlerRecord.getHttpRequest().getExtras());
        crawlerRequestRecord.tagsCreator().bizTags().addCustomKV(REQUEST_AGAIN_TAG, ++count);
        crawlerRequestRecords.add(crawlerRequestRecord);
    }

    private static void initKeywordRecord(CrawlerRequestRecord requestRecord, CrawlerRequestRecord supportSourceRecord, List<CrawlerRecord> crawlerRecords) {
        String source = (String) requestRecord.getHttpRequest().getExtras().get(SOURCE);
        String subid = (String) requestRecord.getHttpRequest().getExtras().get(SUBID);
        String type  = (String) requestRecord.getHttpRequest().getExtras().get("type");
        if(StringUtils.isBlank(source) || StringUtils.isBlank(subid) || StringUtils.isBlank(type)){
            log.error("source or subid or subscribe type is need!");
            return;
        }
        HttpPage supportHttpPage = supportSourceRecord.getInternalDownloadPage();
        List<String> content = supportHttpPage.getJson().jsonPath($_type + ".content").all();
        if (content.size() < 1) {
            log.error("key is null!");
            return;
        }

        for (String data : content) {
            String keyword = JSONObject.parseObject(data).getString("keyword");
            String url = requestRecord.getHttpRequest().getUrl();
            CrawlerRequestRecord keywordRecord = CrawlerRequestRecord.builder()
                    .itemPageRequest(requestRecord)
                    .httpUrl(url)
                    .recordKey(url + keyword + type)
                    .releaseTime(System.currentTimeMillis())
                    .copyBizTags()
                    .copyResultTags()
                    .build();

            HttpRequest httpRequest = keywordRecord.getHttpRequest();
            httpRequest.setMethod(HttpConstant.Method.POST);
            Map<String,Object> params = new HashMap<>();
            params.put("source",source);
            params.put("subid",Integer.parseInt(subid));
            params.put(type,keyword);
            httpRequest.setRequestBody(HttpRequestBody.form(params,"UTF-8"));
            keywordRecord.tagsCreator().bizTags().addKeywords(keyword);
            keywordRecord.getHttpRequest().addExtra("keyword",keyword);
            crawlerRecords.add(keywordRecord);
        }
    }
    @Override
    public void afterExecute(CrawlerRecordContext context) {

    }
}
